package com.szeldon.meteodroid;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.util.Log;

/**
 * Utility class for MeteoDroid. <br/>
 * There are these params in requests:
 * <ul>
 * <li>ntype: seems to be model type, because changes when we change a model (0u-UM; 2n-COAMPS)</li>
 * <li>fdate: forecast date in YYYYMMDD?? - don't know what's the last part... hour?</li>
 * <li>row: row on map?</li>
 * <li>col: column on map?</li>
 * <li>lang: language (pl; )</li>
 * <li>cname: city name (Warszawa; )
 * </ul>
 * I'm not sure what's the connection between row, col and cname.
 * 
 * @author szeldon
 * 
 */
public final class MeteoPlHelper {

    public static final String UM_MODEL_TYPE_ARGUMENT_VALUE = "0u";

    public static final String MODEL_TYPE_ARGUMENT_KEY = "ntype";
    public static final String FORECAST_DATE_ARGUMENT_KEY = "fdate";
    public static final String ROW_ARGUMENT_KEY = "row";
    public static final String COLUMN_ARGUMENT_KEY = "col";
    public static final String LANGUAGE_ARGUMENT_KEY = "lang";
    public static final String CITY_NAME_ARGUMENT_KEY = "cname";

    /**
     * Sends a synchronous request to server with meteorograms. Returns response.
     * 
     * @param forecastDate
     * @param rowOnMap
     * @param columnOnMap
     * @param language
     * @param cityName
     * @return
     * @throws IOException
     * @throws ClientProtocolException
     */
    public static String requestUmModelMeteogram(String forecastDate, int rowOnMap, int columnOnMap, String language,
            String cityName) {
        try {
            DefaultHttpClient client = new DefaultHttpClient();

            // String referer = "http://new.meteo.pl/um/php/mgram_pict.php?" + MODEL_TYPE_ARGUMENT_KEY + "="
            // + UM_MODEL_TYPE_ARGUMENT_VALUE + "&" + FORECAST_DATE_ARGUMENT_KEY + "=" + forecastDate + "&"
            // + ROW_ARGUMENT_KEY + "=" + rowOnMap + "&" + COLUMN_ARGUMENT_KEY + "=" + columnOnMap + "&"
            // + LANGUAGE_ARGUMENT_KEY + "=" + language + "&" + CITY_NAME_ARGUMENT_KEY + "=" + cityName;
            //
            // if (firstRequest(client, forecastDate, rowOnMap, columnOnMap, language, cityName)) {
            // if (otherResourceRequest(client, referer, "http://new.meteo.pl/css/style_all.css", "text/css,*/*;q=0.1"))
            // {
            // if (otherResourceRequest(client, referer, "http://new.meteo.pl/img/exit.gif", "*/*")) {
            // if (otherResourceRequest(client, referer, "http://new.meteo.pl/img/printer.gif", "*/*")) {
            // if (otherResourceRequest(client, referer, "http://new.meteo.pl/um/metco/leg_um_pl.png",
            // "*/*"))
            // if (meteogramLegendRequest(client, forecastDate, rowOnMap, columnOnMap, language,
            // cityName) != null) {
            // return meteogramRequest(client, forecastDate, rowOnMap, columnOnMap, language,
            // cityName);
            // } else {
            // return null;
            // }
            //
            // } else {
            // return null;
            // }
            // } else {
            // return null;
            // }
            // } else {
            // return null;
            // }
            // } else {
            // return null;
            // }

            return firstRequest(client, forecastDate, rowOnMap, columnOnMap, language, cityName);

        } catch (ClientProtocolException e) {
            Log.e("MeteoPl4Android - helper.", "ClientProtocolException.", e);
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            Log.e("MeteoPl4Android - helper.", "IOException.", e);
            return null;
        }
    }

    private static String firstRequest(DefaultHttpClient client, String forecastDate, int rowOnMap, int columnOnMap,
            String language, String cityName) throws ClientProtocolException, IllegalStateException, IOException {

        HttpGet get = new HttpGet("http://new.meteo.pl/um/php/meteorogram_list.php?" + MODEL_TYPE_ARGUMENT_KEY + "="
                + UM_MODEL_TYPE_ARGUMENT_VALUE + "&" + FORECAST_DATE_ARGUMENT_KEY + "=" + forecastDate + "&"
                + ROW_ARGUMENT_KEY + "=" + rowOnMap + "&" + COLUMN_ARGUMENT_KEY + "=" + columnOnMap + "&"
                + LANGUAGE_ARGUMENT_KEY + "=" + language + "&" + CITY_NAME_ARGUMENT_KEY + "=" + cityName);

        createOrReplaceHeader(get, "Connection", "keep-alive");
        createOrReplaceHeader(get, "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, "
                + "like Gecko) Chrome/5.0.375.86 Safari/533.4");
        createOrReplaceHeader(get, "Accept",
                "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
        createOrReplaceHeader(get, "Accept-Encoding", "gzip,deflate,sdch");
        createOrReplaceHeader(get, "Accept-Language", "en-US,en;q=0.8");
        createOrReplaceHeader(get, "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");

        Header[] headers = get.getAllHeaders();
        for (Header currentHeader : headers) {
            Log.d("MeteoPl first request header:" + currentHeader.getName(), currentHeader.getValue());
        }

        HttpResponse response = client.execute(get);

        int responseCode = response.getStatusLine().getStatusCode();
        Log.i("MeteoPl first response code:", "" + responseCode);
        headers = response.getAllHeaders();
        for (Header currentHeader : headers) {
            Log.d("MeteoPl first response header:" + currentHeader.getName(), currentHeader.getValue());
        }

        if (responseCode != 200) {
            throw new IllegalStateException("Problem during communication. First response code=" + responseCode);
        }

        BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        StringBuffer buffer = new StringBuffer();
        String line = null;
        Log.d("MeteoPl read lines:", "");
        while ((line = reader.readLine()) != null) {
            buffer.append(line + "\n");
        }
        Log.d("MeteoPl read lines:", buffer.toString());
        if (buffer.length() == 0) {
            return null;
        }

        return buffer.toString();
    }

    /**
     * @param client
     * @param referer
     * @param url
     * @param accept
     */
    private static boolean otherResourceRequest(DefaultHttpClient client, String referer, String url, String accept)
            throws ClientProtocolException, IOException {
        HttpGet get = new HttpGet(url);

        createOrReplaceHeader(get, "Connection", "keep-alive");
        createOrReplaceHeader(get, "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, "
                + "like Gecko) Chrome/5.0.375.86 Safari/533.4");
        createOrReplaceHeader(get, "Referer", referer);
        createOrReplaceHeader(get, "Accept", accept);
        createOrReplaceHeader(get, "Accept-Encoding", "gzip,deflate,sdch");
        createOrReplaceHeader(get, "Accept-Language", "en-US,en;q=0.8");
        createOrReplaceHeader(get, "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");

        Header[] headers = get.getAllHeaders();
        for (Header currentHeader : headers) {
            Log.d("MeteoPl other resource request header:" + currentHeader.getName(), currentHeader.getValue());
        }

        HttpResponse response = client.execute(get);

        int responseCode = response.getStatusLine().getStatusCode();
        Log.i("MeteoPl other resource response code:", "" + responseCode);
        headers = response.getAllHeaders();
        for (Header currentHeader : headers) {
            Log.d("MeteoPl other resource response header:" + currentHeader.getName(), currentHeader.getValue());
        }

        if (responseCode != 200) {
            throw new IllegalStateException("Problem during communication. Other resource response code="
                    + responseCode);
        }

        BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        StringBuffer buffer = new StringBuffer();
        String line = null;
        Log.d("MeteoPl read lines:", "");
        while ((line = reader.readLine()) != null) {
            buffer.append(line + "\n");
        }
        Log.d("MeteoPl read lines:", buffer.toString());
        if (buffer.length() == 0) {
            return false;
        }

        return true;
    }

    private static byte[] meteogramLegendRequest(DefaultHttpClient client, String forecastDate, int rowOnMap,
            int columnOnMap, String language, String cityName) throws ClientProtocolException, IOException,
            IllegalStateException {

        HttpGet get = new HttpGet("http://new.meteo.pl/um/php/mgram_pict.php?" + MODEL_TYPE_ARGUMENT_KEY + "="
                + UM_MODEL_TYPE_ARGUMENT_VALUE + "&" + FORECAST_DATE_ARGUMENT_KEY + "=" + forecastDate + "&"
                + ROW_ARGUMENT_KEY + "=" + rowOnMap + "&" + COLUMN_ARGUMENT_KEY + "=" + columnOnMap + "&"
                + LANGUAGE_ARGUMENT_KEY + "=" + language);

        createOrReplaceHeader(get, "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, "
                + "like Gecko) Chrome/5.0.375.86 Safari/533.4");
        createOrReplaceHeader(get, "Referer", "http://new.meteo.pl/");
        createOrReplaceHeader(get, "Accept", "*/*");
        createOrReplaceHeader(get, "Accept-Encoding", "gzip,deflate");
        createOrReplaceHeader(get, "Accept-Language", "en-US,en;q=0.8");
        createOrReplaceHeader(get, "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");

        Header[] headers = get.getAllHeaders();
        for (Header currentHeader : headers) {
            Log.i("MeteoPl second request header:" + currentHeader.getName(), currentHeader.getValue());
        }

        HttpResponse response = client.execute(get);

        int responseCode = response.getStatusLine().getStatusCode();
        Log.i("MeteoPl second response code:", "" + responseCode);
        headers = response.getAllHeaders();
        for (Header currentHeader : headers) {
            Log.i("MeteoPl second response header:" + currentHeader.getName(), currentHeader.getValue());
        }

        if (responseCode != 200) {
            throw new IllegalStateException("Problem during communication. Second response code=" + responseCode);
        }

        InputStream inputStream = response.getEntity().getContent();
        ArrayList<Byte> responseList = new ArrayList<Byte>();
        byte[] buffer = new byte[1024];
        int bytesRead = 0;
        while ((bytesRead = inputStream.read(buffer)) > 0) {
            Log.d("bytesRead:", "" + bytesRead);
            for (int i = 0; i < bytesRead; i++) {
                responseList.add(buffer[i]);
            }
        }

        if (responseList.size() == 0) {
            return null;
        }
        byte[] bytesReadArray = new byte[responseList.size()];
        for (int i = 0; i < responseList.size(); i++) {
            bytesReadArray[i] = responseList.get(i);
        }

        return bytesReadArray;

    }

    private static byte[] meteogramRequest(DefaultHttpClient client, String forecastDate, int rowOnMap,
            int columnOnMap, String language, String cityName) throws ClientProtocolException, IOException,
            IllegalStateException {
        HttpGet get = new HttpGet("http://new.meteo.pl/um/php/mgram_pict.php?" + MODEL_TYPE_ARGUMENT_KEY + "="
                + UM_MODEL_TYPE_ARGUMENT_VALUE + "&" + FORECAST_DATE_ARGUMENT_KEY + "=" + forecastDate + "&"
                + ROW_ARGUMENT_KEY + "=" + rowOnMap + "&" + COLUMN_ARGUMENT_KEY + "=" + columnOnMap + "&"
                + LANGUAGE_ARGUMENT_KEY + "=" + language);

        createOrReplaceHeader(get, "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.4 (KHTML, "
                + "like Gecko) Chrome/5.0.375.86 Safari/533.4");
        createOrReplaceHeader(get, "Referer", "http://new.meteo.pl/");
        createOrReplaceHeader(get, "Accept", "*/*");
        createOrReplaceHeader(get, "Accept-Encoding", "gzip,deflate");
        createOrReplaceHeader(get, "Accept-Language", "en-US,en;q=0.8");
        createOrReplaceHeader(get, "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");

        Header[] headers = get.getAllHeaders();
        for (Header currentHeader : headers) {
            Log.i("MeteoPl meteorogram request header:" + currentHeader.getName(), currentHeader.getValue());
        }

        HttpResponse response = client.execute(get);

        int responseCode = response.getStatusLine().getStatusCode();
        Log.i("MeteoPl meteorogram response code:", "" + responseCode);
        headers = response.getAllHeaders();
        for (Header currentHeader : headers) {
            Log.i("MeteoPl meteorogram response header:" + currentHeader.getName(), currentHeader.getValue());
        }

        if (responseCode != 200) {
            throw new IllegalStateException("Problem during communication. Meteorogram response code=" + responseCode);
        }

        InputStream inputStream = response.getEntity().getContent();
        ArrayList<Byte> responseList = new ArrayList<Byte>();
        byte[] buffer = new byte[1024];
        int bytesRead = 0;
        while ((bytesRead = inputStream.read(buffer)) > 0) {
            Log.d("bytesRead:", "" + bytesRead);
            for (int i = 0; i < bytesRead; i++) {
                responseList.add(buffer[i]);
            }
        }

        if (responseList.size() == 0) {
            return null;
        }
        byte[] bytesReadArray = new byte[responseList.size()];
        for (int i = 0; i < responseList.size(); i++) {
            bytesReadArray[i] = responseList.get(i);
        }

        return bytesReadArray;

    }

    /**
     * Creates or if the header is already in given get, replaces it with provided one.
     * 
     * @param get
     * @param headerName
     * @param headerValue
     */
    private static void createOrReplaceHeader(HttpGet get, String headerName, String headerValue) {
        if (get.containsHeader(headerName)) {
            get.removeHeaders(headerName);
        }
        get.addHeader(headerName, headerValue);
    }

}
